package com.poetry.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.poetry.exception.ResourceNotFoundException;
import com.poetry.model.Poem;
import com.poetry.model.User;
import com.poetry.model.dto.UserDTO;
import com.poetry.repository.PoemRepository;
import com.poetry.repository.UserRepository;
import com.poetry.service.UserService;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PoemRepository poemRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public User findById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
    }

    @Override
    public User findByUsername(String username) {
        return userRepository.findByUsername(username)
            .orElseThrow(() -> new ResourceNotFoundException("User not found with username: " + username));
    }

    @Override
    @Transactional
    public User register(UserDTO userDTO) {
        if (userRepository.existsByUsername(userDTO.getUsername())) {
            throw new IllegalArgumentException("Username already exists");
        }
        if (userRepository.existsByEmail(userDTO.getEmail())) {
            throw new IllegalArgumentException("Email already exists");
        }

        User user = new User();
        user.setUsername(userDTO.getUsername());
        user.setEmail(userDTO.getEmail());
        user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        user.setBio(userDTO.getBio());
        return userRepository.save(user);
    }

    @Override
    @Transactional
    public User updateProfile(Long id, UserDTO userDTO) {
        User user = findById(id);
        
        if (!user.getUsername().equals(userDTO.getUsername()) && 
            userRepository.existsByUsername(userDTO.getUsername())) {
            throw new IllegalArgumentException("Username already exists");
        }
        if (!user.getEmail().equals(userDTO.getEmail()) && 
            userRepository.existsByEmail(userDTO.getEmail())) {
            throw new IllegalArgumentException("Email already exists");
        }

        user.setUsername(userDTO.getUsername());
        user.setEmail(userDTO.getEmail());
        user.setBio(userDTO.getBio());
        return userRepository.save(user);
    }

    @Override
    @Transactional
    public void updatePassword(Long id, String currentPassword, String newPassword) {
        User user = findById(id);
        if (!passwordEncoder.matches(currentPassword, user.getPassword())) {
            throw new IllegalArgumentException("Current password is incorrect");
        }
        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);
    }

    @Override
    public List<Poem> findPoemsByUserId(Long userId) {
        return poemRepository.findByAuthorIdOrderByCreatedAtDesc(userId);
    }

    @Override
    public List<Poem> findLikedPoemsByUserId(Long userId) {
        return poemRepository.findLikedPoemsByUserId(userId);
    }

    @Override
    public List<Poem> findBookmarkedPoemsByUserId(Long userId) {
        return poemRepository.findBookmarkedPoemsByUserId(userId);
    }

    @Override
    @Transactional
    public void follow(Long followerId, Long followingId) {
        if (followerId.equals(followingId)) {
            throw new IllegalArgumentException("Cannot follow yourself");
        }
        User follower = findById(followerId);
        User following = findById(followingId);
        follower.getFollowing().add(following);
        userRepository.save(follower);
    }

    @Override
    @Transactional
    public void unfollow(Long followerId, Long followingId) {
        User follower = findById(followerId);
        User following = findById(followingId);
        follower.getFollowing().remove(following);
        userRepository.save(follower);
    }

    @Override
    public boolean isFollowing(Long followerId, Long followingId) {
        return userRepository.existsByFollowerIdAndFollowingId(followerId, followingId);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        if (!userRepository.existsById(id)) {
            throw new ResourceNotFoundException("User not found with id: " + id);
        }
        userRepository.deleteById(id);
    }
} 